home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / incoming / jstools-.6v3 / jstools- / jstools-tk3.6v3.0 / lib / jedit_util.tcl < prev    next >
Encoding:
Text File  |  1995-02-09  |  11.8 KB  |  428 lines

  1. # jedit_util.tcl - utility procedures for jedit, a tk-based editor
  2. # Copyright 1992-1994 by Jay Sekora.  All rights reserved, except 
  3. # that this file may be freely redistributed in whole or in part 
  4. # for non-profit, noncommercial use.
  5.  
  6. # TO DO
  7. #   abbrev fixes:
  8. #     maybe some heuristics for things like plurals
  9. #     maybe a syntax for suffixes (e.g., commit;t -> commitment)
  10. #   file_modes panel
  11. #   documentation for keybindings (automatic documentation?)
  12. #   problem with filename getting set when you cancel Save 
  13. #     for the first time on a new unnamed file
  14. #   improve find panel
  15. #     have find wrap around (if last time didn't match)
  16. #     regex search/replace
  17. #     find all at once (mark) and cycle through with tag nextrange
  18. #   gesture commands
  19. #   autobreaking space a problem if you use two spaces betw sentences
  20. #   word-end punctuation (and heuristics) sd be mode-specific
  21.  
  22. # CHANGES:
  23. #   house(s) the s won't expand
  24. #   return key checkpoints!
  25. #   improved mode handling (hooks)
  26.  
  27. ######################################################################
  28.  
  29. ######################################################################
  30. # basic initialisation
  31. # only has an effect the first time it's called.
  32. ######################################################################
  33.  
  34. proc jedit:init {} {
  35.   global JEDIT_INITIALISED        ;# flag - already called?
  36.   if [info exists JEDIT_INITIALISED] {
  37.     return                ;# only initialise once
  38.   }
  39.   set JEDIT_INITIALISED 1
  40.   
  41.   global J_PREFS            ;# cross-application prefs
  42.   global JEDIT_PREFS            ;# editor prefs (all modes)
  43.   global JEDIT_MODEPREFS        ;# mode-specific prefs
  44.   
  45.   global JEDIT_WINDOW_COUNT        ;# number of toplevel windows
  46.   set JEDIT_WINDOW_COUNT 0
  47.   
  48.   j:jstools_init            ;# prefs, libraries, bindings...
  49.   
  50.   global UNDOPTR            ;# current index into undo ring
  51.   set UNDOPTR 0
  52.   
  53.   global FILE_MODES            ;# filename patterns for modes
  54.                       ;# only first two sublist items matter
  55.   set FILE_MODES {
  56.     {*.c        code        {C source}}
  57.     {*.f        code        {Fortran source}}
  58.     {*.h        code        {C header files}}
  59.     {*.jdoc        jdoc        {document for jdoc app.}}
  60.     {*.jrt        richtext    {rich-text with fonts and other tags}}
  61.     {*.p        code        {Pascal source}}
  62.     {*.sh        code        {Bourne shell script}}
  63.     {*.shar        code        {Bourne shell archive}}
  64.     {*.tcl        tcl        {Tcl scripts}}
  65.     {*.tk        tcl        {Tk/Tcl scripts}}
  66.     {*.exp        tcl        {Expect scripts}}
  67.     {*/.letter        mail        {Mail from tin}}
  68.     {.letter        mail        {Mail from tin}}
  69.     {*/.[a-zA-Z]*    code        {~/.login, etc.}}
  70.     {.[a-zA-Z]*        code        {.login, etc.}}
  71.     {*/draft*/[0-9]*    mh        {MH, exmh, xmh, etc.}}
  72.     {*/tmp/snd.[0-9]*    mail        {elm}}
  73.     {*/tmp/R*[0-9]    mail        {UCB Mail}}
  74.     {*.note        note        {short multi-font note}}
  75.   }
  76.   
  77.   global LINE_MODES            ;# first-line patterns for modes
  78.                       ;# only first two sublist items matter
  79.   set LINE_MODES {
  80.     {%!*        code        {PostScript file}}
  81.     {{#!*/wish*}    tcl        {Tk/Tcl scripts}}
  82.     {{#!*/tclsh*}    tcl        {Tcl scripts}}
  83.     {{#!*/expect*}    tcl        {Expect or Expectk scripts}}
  84.     {#!*        code        {executable script}}
  85.   }
  86.   
  87.   global WORD_END
  88.   set WORD_END {
  89.     ampersand
  90.     apostrophe
  91.     asterisk
  92.     braceright
  93.     bracketright
  94.     colon
  95.     comma
  96.     exclam
  97.     minus
  98.     parenright
  99.     period
  100.     question
  101.     quotedbl
  102.     quoteright
  103.     semicolon
  104.     slash
  105.     underscore
  106.   }
  107.   
  108.   global CUTBUFFER
  109.   set CUTBUFFER {}
  110.   
  111.   global ABBREV                ;# last abbrev expanded
  112.   set ABBREV {}
  113.   global ABBREV_POS            ;# start of last abbrev
  114.   set ABBREV_POS {}
  115.   global MATCH                ;# last match found
  116.   set MATCH {}
  117.   global MATCH_POS            ;# position of last match found
  118.   set MATCH_POS {}
  119.   global ABBREV_LIST            ;# list of abbrevs read from file
  120.   set ABBREV_LIST {}            ;# (not yet used)
  121.   global ABBREVS            ;# text-indexed array of expansions
  122. }
  123.  
  124. ######################################################################
  125. # edit a file
  126. ######################################################################
  127.  
  128. proc jedit:jedit { args } {
  129.   global JEDIT_PREFS
  130.   global JEDIT_MODEPREFS        ;# mode-specific prefs
  131.   global JEDIT_WINDOW_COUNT        ;# number of toplevel windows
  132.   
  133.   j:parse_args {
  134.     {window unspecified}
  135.     {mode default}
  136.     {file {}}
  137.   }
  138.   
  139.   jedit:init                ;# ignored second etc. time it's called
  140.   
  141.   if {"x$mode" == "xdefault"} {        ;# if caller hasn't specified mode
  142.     if {"x$file" != "x"} {        ;#   and we have a filename
  143.       set mode [jedit:guess_mode $file]    ;#     guess the mode
  144.     } else {                ;#   if no filename
  145.       set mode plain            ;#     empty window in plain mode
  146.     }
  147.   }
  148.   
  149.   # pick a window name if the user hasn't supplied one
  150.   if { "x$window" == "xunspecified" } {
  151.     set window [jedit:new_window_name]
  152.   }
  153.   
  154.   if { ! [winfo exists $window] } {
  155.     toplevel $window
  156.   }
  157.   
  158.   incr JEDIT_WINDOW_COUNT        ;# keep count of each window opened
  159.   
  160.   set text [jedit:top_to_text $window]
  161.   
  162.   if {"x$file" != "x"} {
  163.     jedit:set_filename $window $file
  164.   }
  165.   jedit:set_mode $window $mode
  166.   
  167.   jedit:userinit $window $mode $file
  168.   jedit:mkwindow $window
  169.   jedit:apply_mode $window
  170.   jedit:apply_prefs $window
  171.   
  172.   jedit:mkbindings $text $text
  173.   if {[info procs jedit:userhook] == "jedit:userhook"} {
  174.     jedit:userhook $window
  175.   }
  176.   if {"x$file" != "x"} {
  177.     tkwait visibility $text        ;# bug workaround for unpatched tk3.6
  178.     jedit:read $file $text
  179.   }
  180.   
  181.   return $window            ;# for caller to manipulate
  182. }
  183.  
  184. ######################################################################
  185. # get an unused name for a window
  186. ######################################################################
  187.  
  188. proc jedit:new_window_name {} {
  189.   set i 0
  190.   while {[winfo exists .jedit$i]} {
  191.     incr i
  192.   }
  193.   return .jedit$i
  194. }
  195.  
  196. ######################################################################
  197. # user customisation
  198. ######################################################################
  199.  
  200. proc jedit:userinit {window mode file} {
  201.   j:debug "jedit:userinit $window $mode $file"
  202.   global J_PREFS            ;# cross-application prefs
  203.   global JEDIT_MODEPREFS        ;# mode-specific prefs
  204.   global JEDIT_PREFS            ;# editor prefs (all modes)
  205.   
  206.   # read in user's editor preferences
  207.   #
  208.   j:read_prefs -array JEDIT_PREFS \
  209.     -file jedit-defaults {
  210.     {textbg white}
  211.     {textfg black}
  212.     {textsb black}
  213.     {textsf white}
  214.     {textiw 2}
  215.     {textbw 2}
  216.     {textsbw 2}
  217.     {undolevels 2}
  218.   }
  219.   jedit:read_mode_prefs $mode
  220.   jedit:cmd:read_abbrevs
  221.   
  222.   # read in user's .tk/jeditrc.tcl
  223.   j:source_config jeditrc.tcl
  224. }
  225.  
  226. ######################################################################
  227. # apply editor and mode preferences (initially or after they change)
  228. ######################################################################
  229.  
  230. proc jedit:apply_all_prefs { window } {
  231.   global JEDIT_MODEPREFS        ;# mode-specific prefs
  232.   jedit:apply_prefs $window
  233.   jedit:apply_mode $window
  234. }
  235.  
  236. ######################################################################
  237. # apply editor preferences (initially or after they change)
  238. ######################################################################
  239.  
  240. proc jedit:apply_prefs { window } {
  241.   global J_PREFS            ;# cross-application prefs
  242.   global JEDIT_MODEPREFS        ;# mode-specific prefs
  243.   global JEDIT_PREFS            ;# editor prefs (all modes)
  244.   global NAME
  245.   global HOME
  246.   global tk_strictMotif
  247.   
  248.   set text [jedit:top_to_text $window]
  249.   set menubar [jedit:top_to_menubar $window]
  250.   
  251.   # set user's text bindings:
  252.   
  253.   j:tb:init Text
  254.   j:eb:init Entry
  255.  
  256.   if {$J_PREFS(tk_strictMotif)} {
  257.     set tk_strictMotif 1
  258.   } else {
  259.     set tk_strictMotif 0
  260.   }
  261.   
  262.   # following are handled by jedit:apply_mode
  263.   # jedit:configure_text $text
  264.   # jedit:mkmenus $menubar $text
  265.   # jedit:mkbuttonbar $buttonbar $text
  266. }
  267.  
  268. ######################################################################
  269. # abbrev - set an abbreviation (used by .tk/abbrevs.tcl
  270. ######################################################################
  271.  
  272. proc abbrev {{abbrev} {expansion}} {
  273.   global ABBREVS
  274.   
  275.   set ABBREVS($abbrev) $expansion
  276. }
  277.  
  278. ######################################################################
  279. # regsub in selection in t
  280. #   if the original text ends with a newline, it is removed and
  281. #   replaced at the end.
  282. ### SHOULD BE MORE GENERAL (eg entire file)
  283. ######################################################################
  284.  
  285. proc jedit:text_regsub { t regex subst } {
  286.   if { ! [j:text:has_selection $t]} {
  287.     j:alert -text "No selection made in text."
  288.     return 1
  289.   }
  290.   
  291.   jedit:cmd:save_checkpoint $t            ;# save undo information
  292.   
  293.   set finalcr 0
  294.   
  295.   set text [selection get]
  296.   if [regexp -- "\n\$" $text] {
  297.     set text [string trimright $text "\n"]
  298.     set finalcr 1
  299.   }
  300.   
  301.   regsub -all -- $regex $text $subst result
  302.   
  303.   if $finalcr {
  304.     append result "\n"
  305.   }
  306.   
  307.   j:text:replace $t sel.first sel.last $result
  308. }
  309.  
  310. ######################################################################
  311. # pipe selection through command (and replace)
  312. #   if original text has a newline and new text doesn't, a newline
  313. #   is appended.  this is a workaround for some filters that drop the
  314. #   newline.  not perfect, but should be adequate.
  315. ######################################################################
  316.  
  317. proc jedit:pipe { t command } {
  318.   if { ! [j:text:has_selection $t]} {
  319.     j:alert -text "No selection made in text."
  320.     return 1
  321.   }
  322.   
  323.   jedit:cmd:save_checkpoint $t            ;# save undo information
  324.   
  325.   set finalcr 0
  326.   
  327.   set text [selection get]
  328.   if [regexp -- "\n\$" $text] {
  329.     set finalcr 1
  330.   }
  331.   
  332.   if { ! $finalcr } {                ;# doesn't already have newline
  333.     append text "\n"
  334.   }
  335.   
  336.   if [catch { eval exec $command << [list $text] } result] {
  337.     j:alert -text "Error from $command: $result"
  338.     return 1
  339.   }
  340.   
  341.   if {$finalcr && ( ! [regexp -- "\n\$" $result] )} {
  342.     append result "\n"
  343.   }
  344.   
  345.   j:text:replace $t sel.first sel.last $result
  346.   
  347.   return 0
  348. }
  349.  
  350. ######################################################################
  351. # return string with first char capitalised
  352. ######################################################################
  353.  
  354. proc jedit:capitalise {string} {
  355.   set cap [format {%s%s} \
  356.     [string toupper [string range $string 0 0]] \
  357.     [string range $string 1 end]]
  358.   return $cap
  359. }
  360.  
  361. ######################################################################
  362. # return string with first char lowercased
  363. ######################################################################
  364.  
  365. proc jedit:uncapitalise {string} {
  366.   set lc [format {%s%s} \
  367.     [string tolower [string range $string 0 0]] \
  368.     [string range $string 1 end]]
  369.   return $lc
  370. }
  371.  
  372. ######################################################################
  373. # go to a particular line
  374. ######################################################################
  375.  
  376. proc jedit:go_to_line { t {lineno 0} } {
  377.   set result [catch {
  378.     j:tb:move $t $lineno.0
  379.   }]
  380.   if $result then {j:alert -text "`$lineno' is not a valid line number."}
  381. }
  382.  
  383. ######################################################################
  384. # set the filename corresponding to a window.  the window can be
  385. # specified either as a text widget, or as that text widget's
  386. # corresponding toplevel window.
  387. ######################################################################
  388.  
  389. proc jedit:set_filename { w filename } {
  390.   global JEDIT_FILES
  391.   
  392.   if { [winfo class $w] == "Text" } {
  393.     set window [jedit:text_to_top $w]
  394. #    set text $w
  395.   } else {
  396.     set window $w
  397. #    set text [jedit:top_to_text $w]
  398.   }
  399.   
  400.   set JEDIT_FILES($window) $filename
  401. }
  402.  
  403. ######################################################################
  404. # return the filename corresponding to a window.  the window can be
  405. # specified either as a text widget, or as that text widget's
  406. # corresponding toplevel window.  if no filename has been set for that
  407. # window, returns {}.
  408. ######################################################################
  409.  
  410. proc jedit:get_filename { w } {
  411.   global JEDIT_FILES
  412.   
  413.   if { [winfo class $w] == "Text" } {
  414.     set window [jedit:text_to_top $w]
  415. #    set text $w
  416.   } else {
  417.     set window $w
  418. #    set text [jedit:top_to_text $w]
  419.   }
  420.   
  421.   if [info exists JEDIT_FILES($window)] {
  422.     return $JEDIT_FILES($window)
  423.   } else {
  424.     return {}
  425.   }
  426. }
  427.